//
// JavaRunner
//
// Copyright (C) jextra.net.
//
//  This file is part of the Crack build system.
//
//  The Crack build system is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The Crack build system is distributed in the hope that it will be 
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the Crack build system; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.crack.tool;

import java.io.*;
import java.util.*;

/**
 * Forks off a new JVM.
 */
public class JavaRunner
{
    // ============================================================
    // Fields
    // ============================================================

    private ProcessExecutor fork;
    private String javaExecutable;
    private List<String> jvmArgs;
    private Set<File> classpathFiles;
    private String className;
    private List<String> args;

    // ============================================================
    // Constructors
    // ============================================================

    public JavaRunner()
    {
        fork = new ProcessExecutor();
        javaExecutable = "java";
        jvmArgs = new ArrayList<String>();
        classpathFiles = new LinkedHashSet<File>();
        args = new ArrayList<String>();
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    public void setDirectory( File dir )
    {
        fork.setDirectory( dir );
    }

    public File getDirectory()
    {
        return fork.getDirectory();
    }

    public String getJavaExecutable()
    {
        return javaExecutable;
    }

    public void setJavaExecutable( String javaExecutable )
    {
        this.javaExecutable = javaExecutable;
    }

    public void addJVMArgs( String ... args )
    {
        for ( String arg : args )
        {
            jvmArgs.add( arg );
        }
    }

    public Collection<String> getJVMArgs()
    {
        return jvmArgs;
    }

    public void addClasspathFile( File file )
    {
        classpathFiles.add( file );
    }

    public void addClasspathFiles( Collection<File> files )
    {
        if ( files == null )
        {
            // Nothing to do.
            return;
        }

        classpathFiles.addAll( files );
    }

    public Collection<File> getClasspathFiles()
    {
        return classpathFiles;
    }

    public String getClasspath()
        throws IOException
    {
        StringBuilder builder = new StringBuilder();
        for ( File file : classpathFiles )
        {
            // A null file is most likely from the file not actually existing.
            if ( file == null )
            {
                continue;
            }

            if ( builder.length() > 0 )
            {
                builder.append( File.pathSeparator );
            }

            builder.append( file.getCanonicalPath() );
        }

        return builder.toString();
    }

    public String getClassName()
    {
        return className;
    }

    public void setClassName( String className )
    {
        this.className = className;
    }

    public void addArgs( String ... newArgs )
    {
        for ( String arg : newArgs )
        {
            args.add( arg );
        }
    }

    public Collection<String> getArgs()
    {
        return args;
    }

    public int run()
        throws Exception
    {
        List<String> runningArgs = new ArrayList<String>();

        runningArgs.add( javaExecutable );

        for ( String jvmArg : jvmArgs )
        {
            runningArgs.add( jvmArg );
        }

        String classpath = getClasspath();
        if ( classpath != null )
        {
            runningArgs.add( "-cp" );
            runningArgs.add( classpath );
        }

        runningArgs.add( className );

        for ( String arg : args )
        {
            runningArgs.add( arg );
        }

        System.out.println( runningArgs );
        return fork.execute( runningArgs );
    }

    public int getExitStatus()
    {
        return fork.getExitStatus();
    }
}
